#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unity.h"
#include "mock_bsp_test_commom.h"  // 假设这是包含rt_ATRWrite和rt_ATCRead声明的头文件

#include "rt_CMDProc.h"

// Test instance and service structures
XRt1553B testInstance;
B1553_BusService testBusServ;

void setUp(void)
{
    // Initialize structures before each test
    memset(&testInstance, 0, sizeof(XRt1553B));
    memset(&testBusServ, 0, sizeof(B1553_BusService));
}

void tearDown(void)
{
    // Cleanup after each test (if needed)
}

// Test case: No message available
void test_rt_CMDProc_NoMessage(void)
{
    // Arrange
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 0);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(0, result);
}

// Test case: Message with error status
void test_rt_CMDProc_MessageError(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc cmdInfoWithErr = {0};
    cmdInfoWithErr.blk_err_stat = 0x02; // Some error status
    
    // Set up previous message with error
    testBusServ.cmdInfo.blk_err_stat = 0x02;
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(-1, result);
    TEST_ASSERT_EQUAL(0x02, testBusServ.ErrorState);
}

// Test case: Duplicate message on A/B bus
void test_rt_CMDProc_DuplicateMessage(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc currentCmd = {0};
    currentCmd.CMDWord = 0x1234;
    currentCmd.DataBlkPtr_or_ModeWord = 0x5678;
    currentCmd.BUSA_or_BUSB = 1; // Different bus
    
    // Set up previous message to be identical except for bus
    testBusServ.cmdInfo.CMDWord = 0x1234;
    testBusServ.cmdInfo.DataBlkPtr_or_ModeWord = 0x5678;
    testBusServ.cmdInfo.BUSA_or_BUSB = 0;
    

    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&currentCmd);


    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(0, result);
}

// Test case: Broadcast message - Position/Altitude with rollover
void test_rt_CMDProc_BroadcastPosAltWithRollover(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc broadcastPosAltCmd = {0};
    broadcastPosAltCmd.RTaddr = B1553_BCST_RTADDR; // 31
    broadcastPosAltCmd.SubAddr_or_ModeCMD = B1553_POSALT_SUBADDR;
    broadcastPosAltCmd.CircBuff_rollover = 1;
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&broadcastPosAltCmd);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(1, result);
    TEST_ASSERT_EQUAL(1, testBusServ.MsgBcst_PosAlt_cnt);
}

// Test case: Broadcast message - Position/Altitude without rollover
void test_rt_CMDProc_BroadcastPosAltWithoutRollover(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc broadcastPosAltCmd = {0};
    broadcastPosAltCmd.RTaddr = B1553_BCST_RTADDR; // 31
    broadcastPosAltCmd.SubAddr_or_ModeCMD = B1553_POSALT_SUBADDR;
    broadcastPosAltCmd.CircBuff_rollover = 0; // No rollover
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&broadcastPosAltCmd);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(0, result);
    TEST_ASSERT_EQUAL(0, testBusServ.MsgBcst_PosAlt_cnt); // Should not increment
}

// Test case: Broadcast message - DateTime
void test_rt_CMDProc_BroadcastDateTime(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc broadcastDateTimeCmd = {0};
    broadcastDateTimeCmd.RTaddr = B1553_BCST_RTADDR; // 31
    broadcastDateTimeCmd.SubAddr_or_ModeCMD = B1553_DATATIME_SUBADDR;
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&broadcastDateTimeCmd);
    
    // Expect rt_RecvDateTime to be called
    rt_RecvDateTime_Expect(&testInstance, &testBusServ);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(1, result);
    TEST_ASSERT_EQUAL(1, testBusServ.MsgBCST_DataTime_cnt);
}

// Test case: Broadcast message - Mode Code
void test_rt_CMDProc_BroadcastModeCode(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc broadcastModeCodeCmd = {0};
    broadcastModeCodeCmd.RTaddr = B1553_BCST_RTADDR; // 31
    broadcastModeCodeCmd.SubAddr_or_ModeCMD = B1553_MODECODE_SUBADDR;
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&broadcastModeCodeCmd);
    
    // Expect rt_ModeCode_proc to be called
    rt_ModeCode_proc_Expect(&testInstance, &testBusServ);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(1, result);
}

// Test case: Non-matching RT address
void test_rt_CMDProc_NonMatchingRTAddress(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc wrongRTCmd = {0};
    wrongRTCmd.RTaddr = 10; // Not our RT address or broadcast
    wrongRTCmd.SubAddr_or_ModeCMD = B1553_DATAWRAP_SUBADDR;
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&wrongRTCmd);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(0, result);
}

// Test case: Data Wrap - Transmit
void test_rt_CMDProc_DataWrapTransmit(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc dataWrapCmd = {0};
    dataWrapCmd.RTaddr = B1553_MY_RTADDR;
    dataWrapCmd.SubAddr_or_ModeCMD = B1553_DATAWRAP_SUBADDR;
    dataWrapCmd.T_or_R = 1; // Transmit
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&dataWrapCmd);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(1, result);
    TEST_ASSERT_EQUAL(1, testBusServ.Msg_DataWrap_cnt);
}

// Test case: Data Wrap - Receive
void test_rt_CMDProc_DataWrapReceive(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc dataWrapCmd = {0};
    dataWrapCmd.RTaddr = B1553_MY_RTADDR;
    dataWrapCmd.SubAddr_or_ModeCMD = B1553_DATAWRAP_SUBADDR;
    dataWrapCmd.T_or_R = 0; // Receive
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&dataWrapCmd);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(0, result);
    TEST_ASSERT_EQUAL(0, testBusServ.Msg_DataWrap_cnt); // Should not increment
}

// Test case: Acquisition Transfer
void test_rt_CMDProc_AcqTrans(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc acqTransCmd = {0};
    acqTransCmd.RTaddr = B1553_MY_RTADDR;
    acqTransCmd.SubAddr_or_ModeCMD = B1553_ACQTRANS_SUBADDR;
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&acqTransCmd);
    
    // Expect rt_AcqTrans_proc to be called
    rt_AcqTrans_proc_Expect(&testInstance, &acqTransCmd, &testBusServ);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(0, result);
}

// Test case: Distribution Transfer
void test_rt_CMDProc_DistrbTrans(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc distTransCmd = {0};
    distTransCmd.RTaddr = B1553_MY_RTADDR;
    distTransCmd.SubAddr_or_ModeCMD = B1553_DISTRBTRANS_SUBADDR;
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&distTransCmd);
    
    // Expect rt_DistrbTrans_proc to be called
    rt_DistrbTrans_proc_Expect(&testInstance, &distTransCmd, &testBusServ);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(0, result);
}

// Test case: Unknown subaddress
void test_rt_CMDProc_UnknownSubAddress(void)
{
    // Arrange
    struct XRt1553B_MsgBlkDesc unknownCmd = {0};
    unknownCmd.RTaddr = B1553_MY_RTADDR;
    unknownCmd.SubAddr_or_ModeCMD = 20; // Unknown subaddress
    
    XRt1553B_GetCMDInfo_ExpectAndReturn(&testInstance, NULL, 1);
    XRt1553B_GetCMDInfo_IgnoreArg_CMDInfo();
    XRt1553B_GetCMDInfo_ReturnThruPtr_CMDInfo(&unknownCmd);

    // Act
    int result = rt_CMDProc(&testInstance, &testBusServ);

    // Assert
    TEST_ASSERT_EQUAL(0, result);
}